package fr.lip6.meta.ple.generation.strategy;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.gmt.modisco.java.AbstractTypeDeclaration;
import org.eclipse.gmt.modisco.java.Model;
import org.eclipse.gmt.modisco.java.NamedElement;
import org.eclipse.gmt.modisco.java.Package;
import org.eclipse.gmt.modisco.java.emf.JavaPackage;
import org.eclipse.gmt.modisco.java.emf.impl.PackageImpl;

import fr.lip6.meta.ple.generation.fh.java.GenerateFromXmiFHJava;

public abstract class GenerateFromXmiStrategy implements GenerationStrategy {
	public static ArrayList<String> importedpackage = new ArrayList<String>();
	public static ArrayList<String> subpackage = new ArrayList<String>();
	public static ArrayList<Package> packages = new ArrayList<Package>();
	
	public static Resource loadJavaModel(String path) {

		Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*",
				new XMIResourceFactoryImpl());


		ResourceSet rs = new ResourceSetImpl();


		URI uri = URI.createFileURI(path);

		rs.getPackageRegistry().put(JavaPackage.eNS_URI,
				JavaPackage.eINSTANCE);
		XMIResourceImpl resource = (XMIResourceImpl) rs.getResource(uri, true);


		return resource;
	}


	public static Model loadModiscoJavaModel(String path) {

		Resource resource = loadJavaModel(path);


		Model model = (Model) resource.getContents().get(0);

		return model;

	}


	public ResourceSet save1(Model model, File f) {
		ResourceSet rs = new ResourceSetImpl();
		Resource.Factory.Registry registry =
				rs.getResourceFactoryRegistry();
		Map<String,Object> m = registry.getExtensionToFactoryMap();
		m.put("xmi", new XMIResourceFactoryImpl());
		m.put("ecore", new EcoreResourceFactoryImpl());
		rs.getPackageRegistry().put(JavaPackage.eNS_URI,
				JavaPackage.eINSTANCE);
		Resource packageResource =
				rs.createResource(URI.createFileURI("java.ecore"));
		packageResource.getContents().add(JavaPackage.eINSTANCE);
		try {
			packageResource.load(null);
		} catch (IOException e1) {

		}
		URI uri = URI.createFileURI(f.getAbsolutePath());
		Resource resource = rs.createResource(uri);
		resource.getContents().add(model);
		try {
			HashMap<String, Boolean> options = new HashMap<String,
					Boolean>();
			options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
			resource.save(options);
		} catch (IOException e){  }
		return rs;
	}

	public ResourceSet save(Model model, File f) {

		ResourceSet rs = new ResourceSetImpl();
		Resource.Factory.Registry registry =rs.getResourceFactoryRegistry();
		Map<String,Object> m = registry.getExtensionToFactoryMap();
		m.put("*", new XMIResourceFactoryImpl());
		//rs.getPackageRegistry().put(org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage.eINSTANCE.getNsURI(), org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage.eINSTANCE);
		rs.getPackageRegistry().put(JavaPackage.eNS_URI,JavaPackage.eINSTANCE);


		URI uri = URI.createFileURI(f.getAbsolutePath());

		Resource resource = rs.createResource(uri);

		resource.getContents().add(model);
		try {
			HashMap<String, Boolean> options = new HashMap<String,
					Boolean>();
			options.put(XMIResource.OPTION_SCHEMA_LOCATION_IMPLEMENTATION, Boolean.TRUE);
			resource.save(options);
		} catch (IOException e) { e.printStackTrace(); }
		return rs;
	}

	public static void readPackageImported(Package pckg, String parent) {
		EList<Package> ownedPckgList = pckg.getOwnedPackages();

		if (ownedPckgList.size() == 0) {
			if (!importedpackage.contains("import "+parent+pckg.getName())) {
				importedpackage.add("import "+parent+pckg.getName());
			}
		} else {
			for(Package p1 : ownedPckgList) {
				readPackageImported(p1, parent+pckg.getName()+".");
			}
		}
	}

	public static void readsubpackage(Package p12, String parent) {
		EList<Package>	pac=p12.getOwnedPackages();
		EList<AbstractTypeDeclaration> cla=p12.getOwnedElements();

		if(pac.size() == 0) {
			//if(!subpackage.contains(parent +p12.getName()+""))
			{

				if(parent.equals(""))
				{

					subpackage.add(p12.getName()+"");
					p12.setName(p12.getName()+"");
					packages.add(p12);

				}
				else
				{

					subpackage.add(parent+p12.getName()+"");
					p12.setName(parent+p12.getName()+"");
					packages.add(p12);
				}
			}

		}
		else if(cla.size()!=0)
		{
			if(parent.equals(""))
			{

				subpackage.add(p12.getName()+"");

				packages.add(p12);
			}
			else
			{

				subpackage.add(parent+p12.getName()+"");
				p12.setName(parent+p12.getName()+"");
				packages.add(p12);
			}
			for(Package p1: pac)
			{
				readsubpackage(p1,p12.getName()+".");
			}
		}
		else
		{
			for(Package p1: pac)
			{
				readsubpackage(p1,parent+p12.getName()+".");
			}
		}

	}

	public static PackageImpl readpackage(String path, String packagename) {
		Model model = loadModiscoJavaModel(path);
		Iterator<Package> packages = model.getOwnedElements().iterator();
		PackageImpl p = null;

		while (packages.hasNext()) {
			PackageImpl pckg = (PackageImpl) packages.next();

			if (pckg.isProxy()) {
				readPackageImported(pckg, "");
			}

			GenerateFromXmiFHJava.packages.clear();
			GenerateFromXmiFHJava.readsubpackage(pckg, "");
			//ArrayList<Package> packages1=GnerateXmi.pacs;

			for(Package package1 : GenerateFromXmiFHJava.packages) {
				if (package1.getName().equals(packagename)) {
					p = (PackageImpl) package1;
					break;
				}
			}
		}

		return p;
	}

	public static String getImportName(	EList<Package> ownedPackages,
												NamedElement importedElement,
												String packageName	) {
		if (ownedPackages.size() > 0) {
			for(Package pckg : ownedPackages) {
				EList<AbstractTypeDeclaration> typeDecls = pckg.getOwnedElements();
				String currentPckgName = (packageName.equals("") ? "" : packageName+".") + pckg.getName();
				String nextPckgName;

				if (pckg == importedElement)
					return currentPckgName + ".*";

				for (AbstractTypeDeclaration typeDecl : typeDecls) {
					if (typeDecl == importedElement)
						return currentPckgName + "." + typeDecl.getName();
				}

				nextPckgName = getImportName(pckg.getOwnedPackages(), importedElement, currentPckgName);

				if (nextPckgName != null)
					return nextPckgName;
			}
		}

		return null;
	}
}
